package academic.ui.client.widgets;

import academic.ui.client.animation.FadeAnimation;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

import ui.client.GenericContainerTag;

public final class FadePanel extends Composite implements 
    HasOpenHandlers<FadePanel>, HasCloseHandlers<FadePanel> {

  private static final String STYLENAME_SUFFIX_CLOSED = "closed";


  private static final String STYLENAME_CONTENT = "fadeContent";

  /**
   * The {@link Animation} used to open and close the content.
   */
  private static FadeAnimation contentAnimation;

  /**
   * top level widget. The first child will be a reference to {@link #header}.
   * The second child will be a reference to {@link #contentWrapper}.
   */
  private final GenericContainerTag mainPanel = new GenericContainerTag("div");

  /**
   * The wrapper around the content widget.
   */
  public final SimplePanel contentWrapper = new SimplePanel();

  /**
   * holds the header widget.
   */

  private boolean isAnimationEnabled = false;

  public boolean isOpen = false;

  /**
   * Creates an empty DisclosurePanel that is initially closed.
   */
  public FadePanel() {
    initWidget(mainPanel);
    mainPanel.add(contentWrapper);
    DOM.setStyleAttribute(contentWrapper.getElement(),"zoom","1");
    setStyleName("fadePanel");
    setContentDisplay(false);
  }


  public void add(Widget w) {
    if (this.getContent() == null) {
      setContent(w);
    } else {
      throw new IllegalStateException(
          "A FadePanel can only contain one widget.");
    }
  }

  public HandlerRegistration addCloseHandler(
      CloseHandler<FadePanel> handler) {
    return addHandler(handler, CloseEvent.getType());
  }

  /**
   * Attaches an event handler to the panel to receive {@link FadeEvent}
   * notification.
   * 
   * @param handler the handler to be added (should not be null)
   * @deprecated Use {@link DisclosurePanel#addOpenHandler(OpenHandler)} and
   *             {@link DisclosurePanel#addCloseHandler(CloseHandler)} instead
   */

  public HandlerRegistration addOpenHandler(OpenHandler<FadePanel> handler) {
    return addHandler(handler, OpenEvent.getType());
  }

  public void clear() {
    setContent(null);
  }

  /**
   * Gets the widget that was previously set in {@link #setContent(Widget)}.
   * 
   * @return the panel's current content widget
   */
  public Widget getContent() {
    return contentWrapper.getWidget();
  }

  public boolean isAnimationEnabled() {
    return isAnimationEnabled;
  }

  /**
   * Determines whether the panel is open.
   * 
   * @return <code>true</code> if panel is in open state
   */
  public boolean isOpen() {
    return isOpen;
  }

 

  public boolean remove(Widget w) {
    if (w == getContent()) {
      setContent(null);
      return true;
    }
    return false;
  }


  public void setAnimationEnabled(boolean enable) {
    isAnimationEnabled = enable;
  }

  /**
   * Sets the content widget which can be opened and closed by this panel. If
   * there is a preexisting content widget, it will be detached.
   * 
   * @param content the widget to be used as the content panel
   */
  public void setContent(Widget content) {
    final Widget currentContent = getContent();

    // Remove existing content widget.
    if (currentContent != null) {
      contentWrapper.setWidget(null);
      currentContent.removeStyleName(STYLENAME_CONTENT);
    }

    // Add new content widget if != null.
    if (content != null) {
      contentWrapper.setWidget(content);
      contentWrapper.setStyleName("relativeNoSpace");
      content.addStyleName(STYLENAME_CONTENT);
      setContentDisplay(false);
    }
  }
  
  /**
   * fades in the FadePanel
   * in doing so also turns on animations
   * if it is already visible then do nothing
   */
  public void fadeIn()
  {
	  setAnimationEnabled(true);
	  if(!this.isOpen)
		  setOpen(true);
  }
  
  public void fadeOut()
  {
	  setAnimationEnabled(true);
	  if(this.isOpen)
		  setOpen(false);
  }

  /**
   * Changes the visible state of this <code>FadePanel</code>.
   * 
   * @param isOpen <code>true</code> to open the panel, <code>false</code> to
   *          close
   */
  public void setOpen(boolean isOpen) {
    if (this.isOpen != isOpen) {
      this.isOpen = isOpen;
      setContentDisplay(true);
      fireEvent();
    }
  }

  private void fireEvent() {
    if (isOpen) {
      OpenEvent.fire(this, this);
    } else {
      CloseEvent.fire(this, this);
    }
  }

  private void setContentDisplay(boolean animate) {
    if (isOpen) {
      removeStyleDependentName(STYLENAME_SUFFIX_CLOSED);
      addStyleDependentName("open");
    } else {
      removeStyleDependentName("open");
      addStyleDependentName(STYLENAME_SUFFIX_CLOSED);
    }

    if (getContent() != null) {
      if (contentAnimation == null) {
        contentAnimation = new FadeAnimation();
      }
      contentAnimation.setOpen(this, animate && isAnimationEnabled);
    }
  }


public void fadeIn(int time) {
	contentAnimation.setAnimationTime(time);
	fadeIn();
}
}
